
// 3DModelViewerView.cpp : implementation of the CMy3DModelViewerView class
//

#include "stdafx.h"
// SHARED_HANDLERS can be defined in an ATL project implementing preview, thumbnail
// and search filter handlers and allows sharing of document code with that project.
#ifndef SHARED_HANDLERS
#include "3DModelViewer.h"
#endif

#include "3DModelViewerDoc.h"
#include "3DModelViewerView.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// CMy3DModelViewerView

IMPLEMENT_DYNCREATE(CMy3DModelViewerView, CView)

BEGIN_MESSAGE_MAP(CMy3DModelViewerView, CView)
	// Standard printing commands
	ON_COMMAND(ID_FILE_PRINT, &CView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_DIRECT, &CView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_PREVIEW, &CMy3DModelViewerView::OnFilePrintPreview)
	ON_WM_CONTEXTMENU()
	ON_WM_RBUTTONUP()
	ON_WM_CREATE()
	ON_WM_DESTROY()
	ON_WM_SIZE()
	ON_WM_ERASEBKGND()
END_MESSAGE_MAP()

// CMy3DModelViewerView construction/destruction

CMy3DModelViewerView::CMy3DModelViewerView()
{
	// TODO: add construction code here

}

CMy3DModelViewerView::~CMy3DModelViewerView()
{
}

BOOL CMy3DModelViewerView::PreCreateWindow(CREATESTRUCT& cs)
{
	// TODO: Modify the Window class or styles here by modifying
	//  the CREATESTRUCT cs

	//Modify the style to avoid opengl draw on another window
	cs.style |= WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
	return CView::PreCreateWindow(cs);
}

// CMy3DModelViewerView drawing

void CMy3DModelViewerView::OnDraw(CDC* /*pDC*/)
{
	CMy3DModelViewerDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;

	// TODO: add draw code for native data here
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	RenderScene();
	glFinish();
	SwapBuffers(m_pDC->GetSafeHdc());
}


// CMy3DModelViewerView printing


void CMy3DModelViewerView::OnFilePrintPreview()
{
#ifndef SHARED_HANDLERS
	AFXPrintPreview(this);
#endif
}

BOOL CMy3DModelViewerView::OnPreparePrinting(CPrintInfo* pInfo)
{
	// default preparation
	return DoPreparePrinting(pInfo);
}

void CMy3DModelViewerView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: add extra initialization before printing
}

void CMy3DModelViewerView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: add cleanup after printing
}

void CMy3DModelViewerView::OnRButtonUp(UINT /* nFlags */, CPoint point)
{
	ClientToScreen(&point);
	OnContextMenu(this, point);
}

void CMy3DModelViewerView::OnContextMenu(CWnd* /* pWnd */, CPoint point)
{
#ifndef SHARED_HANDLERS
	theApp.GetContextMenuManager()->ShowPopupMenu(IDR_POPUP_EDIT, point.x, point.y, this, TRUE);
#endif
}


// CMy3DModelViewerView diagnostics

#ifdef _DEBUG
void CMy3DModelViewerView::AssertValid() const
{
	CView::AssertValid();
}

void CMy3DModelViewerView::Dump(CDumpContext& dc) const
{
	CView::Dump(dc);
}

CMy3DModelViewerDoc* CMy3DModelViewerView::GetDocument() const // non-debug version is inline
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CMy3DModelViewerDoc)));
	return (CMy3DModelViewerDoc*)m_pDocument;
}
#endif //_DEBUG


// CMy3DModelViewerView message handlers


int CMy3DModelViewerView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (CView::OnCreate(lpCreateStruct) == -1)
		return -1;

	// TODO:  Add your specialized creation code here
	InitializeOpenGL();
	return 0;
}


void CMy3DModelViewerView::OnDestroy()
{
	CView::OnDestroy();

	// TODO: Add your message handler code here
	//make the RC non-current
	if (!wglMakeCurrent(0, 0))
	{
		MessageBox(_T("Could not make RC non-current."));
	}
	//delete the rendering contex
	if (!wglDeleteContext(m_hRC))
	{
		MessageBox(_T("Could not delete RC."));
	}
	//delete the DC
	if (m_pDC)
	{
		delete m_pDC;
	}
	m_pDC = NULL;
}


void CMy3DModelViewerView::OnSize(UINT nType, int cx, int cy)
{
	CView::OnSize(nType, cx, cy);

	// TODO: Add your message handler code here
	if (0 >= cx || 0 >= cy)
	{
		return;
	}
	GLdouble aspectRatio;		//ratio = width/height
	//select the full client area
	glViewport(0, 0, cx, cy);
	//compute the aspect ratio
	aspectRatio = (GLdouble)cx/(GLdouble)cy;
	//select the projection matrix and clear it
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(45.0f, aspectRatio, .01f, 200.0f);		//for 3D
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
}


BOOL CMy3DModelViewerView::OnEraseBkgnd(CDC* pDC)
{
	// TODO: Add your message handler code here and/or call default

	//avoid shining when changing the size of window
	//return CView::OnEraseBkgnd(pDC);
	return TRUE;
}


BOOL CMy3DModelViewerView::InitializeOpenGL()
{
	//Get a DC for the Client Area
	m_pDC = new CClientDC(this);
	if (!m_pDC)
	{
		ASSERT(0);
		return FALSE;
	}

	if (!SetupPixelFormat())
	{
		return FALSE;
	}
	//Create Rendering Context
	m_hRC = ::wglCreateContext(m_pDC->GetSafeHdc());
	if (m_hRC == 0)
	{
		ASSERT(0);
		return FALSE;
	}
	//Make the RC Current
	if (!::wglMakeCurrent(m_pDC->GetSafeHdc(), m_hRC))
	{
		ASSERT(0);
		return FALSE;
	}
	//Specify Black as the clear color
	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
	//Specify the back of buffer as clear depth
	glClearDepth(1.0f);
	//Enable Depth Testing
	glEnable(GL_DEPTH_TEST);
	return TRUE;
}

BOOL CMy3DModelViewerView::SetupPixelFormat()
{
	static PIXELFORMATDESCRIPTOR pfd = 
	{
		sizeof(PIXELFORMATDESCRIPTOR),		//size of this pfd
		1,									//version number
		PFD_DRAW_TO_WINDOW |				//support window
		PFD_SUPPORT_OPENGL |				//support opengl
		PFD_DOUBLEBUFFER,					//double buffered
		PFD_TYPE_RGBA,						//RGBA type
		24,									//24-bit color depth
		0,0,0,0,0,0,						//color bits ignored
		0,									//no alpha buffer
		0,									//shift bit ignored
		0,									//no accumulation buffer
		0,0,0,0,							//accum bits ignored
		16,									//16-bit z-buffer
		0,									//no stencil buffer
		0,									//no auxiliary buffer
		PFD_MAIN_PLANE,						//main layer
		0,									//reserved
		0,0,0								//layer masks ignored
	};
	int m_nPixelFormat = ::ChoosePixelFormat(m_pDC->GetSafeHdc(), &pfd);
	if (m_nPixelFormat == 0)
	{
		ASSERT(0);
		return FALSE;
	}
	if (!::SetPixelFormat(m_pDC->GetSafeHdc(), m_nPixelFormat, &pfd))
	{
		ASSERT(0);
		return FALSE;
	}
	return TRUE;
}

void CMy3DModelViewerView::RenderScene()
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear Screen And Depth Buffer

	glLoadIdentity();                                   // Reset The Current Modelview Matrix

	glTranslatef(-1.5f,0.0f,-6.0f);                     // Move Left 1.5 Units And Into The Screen 6.0

	glRotatef(30,0.0f,1.0f,0.0f);                       // Rotate The Triangle On The Y axis ( NEW )

	glBegin(GL_TRIANGLES);                              // Start Drawing A Triangle

	glColor3f(1.0f,0.0f,0.0f);                      // Red

	glVertex3f( 0.0f, 1.0f, 0.0f);                  // Top Of Triangle (Front)

	glColor3f(0.0f,1.0f,0.0f);                      // Green

	glVertex3f(-1.0f,-1.0f, 1.0f);                  // Left Of Triangle (Front)

	glColor3f(0.0f,0.0f,1.0f);                      // Blue

	glVertex3f( 1.0f,-1.0f, 1.0f);                  // Right Of Triangle (Front)

	glColor3f(1.0f,0.0f,0.0f);                      // Red

	glVertex3f( 0.0f, 1.0f, 0.0f);                  // Top Of Triangle (Right)

	glColor3f(0.0f,0.0f,1.0f);                      // Blue

	glVertex3f( 1.0f,-1.0f, 1.0f);                  // Left Of Triangle (Right)

	glColor3f(0.0f,1.0f,0.0f);                      // Green

	glVertex3f( 1.0f,-1.0f, -1.0f);                 // Right Of Triangle (Right)

	glColor3f(1.0f,0.0f,0.0f);                      // Red

	glVertex3f( 0.0f, 1.0f, 0.0f);                  // Top Of Triangle (Back)

	glColor3f(0.0f,1.0f,0.0f);                      // Green

	glVertex3f( 1.0f,-1.0f, -1.0f);                 // Left Of Triangle (Back)

	glColor3f(0.0f,0.0f,1.0f);                      // Blue

	glVertex3f(-1.0f,-1.0f, -1.0f);                 // Right Of Triangle (Back)

	glColor3f(1.0f,0.0f,0.0f);                      // Red

	glVertex3f( 0.0f, 1.0f, 0.0f);                  // Top Of Triangle (Left)

	glColor3f(0.0f,0.0f,1.0f);                      // Blue

	glVertex3f(-1.0f,-1.0f,-1.0f);                  // Left Of Triangle (Left)

	glColor3f(0.0f,1.0f,0.0f);                      // Green

	glVertex3f(-1.0f,-1.0f, 1.0f);                  // Right Of Triangle (Left)

	glEnd();                                            // Done Drawing The Pyramid



	glLoadIdentity();                                   // Reset The Current Modelview Matrix

	glTranslatef(1.5f,0.0f,-7.0f);                      // Move Right 1.5 Units And Into The Screen 7.0

	glRotatef(25,1.0f,1.0f,1.0f);                   // Rotate The Quad On The X axis ( NEW )

	glBegin(GL_QUADS);                                  // Draw A Quad

	glColor3f(0.0f,1.0f,0.0f);                      // Set The Color To Green

	glVertex3f( 1.0f, 1.0f,-1.0f);                  // Top Right Of The Quad (Top)

	glVertex3f(-1.0f, 1.0f,-1.0f);                  // Top Left Of The Quad (Top)

	glVertex3f(-1.0f, 1.0f, 1.0f);                  // Bottom Left Of The Quad (Top)

	glVertex3f( 1.0f, 1.0f, 1.0f);                  // Bottom Right Of The Quad (Top)

	glColor3f(1.0f,0.5f,0.0f);                      // Set The Color To Orange

	glVertex3f( 1.0f,-1.0f, 1.0f);                  // Top Right Of The Quad (Bottom)

	glVertex3f(-1.0f,-1.0f, 1.0f);                  // Top Left Of The Quad (Bottom)

	glVertex3f(-1.0f,-1.0f,-1.0f);                  // Bottom Left Of The Quad (Bottom)

	glVertex3f( 1.0f,-1.0f,-1.0f);                  // Bottom Right Of The Quad (Bottom)

	glColor3f(1.0f,0.0f,0.0f);                      // Set The Color To Red

	glVertex3f( 1.0f, 1.0f, 1.0f);                  // Top Right Of The Quad (Front)

	glVertex3f(-1.0f, 1.0f, 1.0f);                  // Top Left Of The Quad (Front)

	glVertex3f(-1.0f,-1.0f, 1.0f);                  // Bottom Left Of The Quad (Front)

	glVertex3f( 1.0f,-1.0f, 1.0f);                  // Bottom Right Of The Quad (Front)

	glColor3f(1.0f,1.0f,0.0f);                      // Set The Color To Yellow

	glVertex3f( 1.0f,-1.0f,-1.0f);                  // Top Right Of The Quad (Back)

	glVertex3f(-1.0f,-1.0f,-1.0f);                  // Top Left Of The Quad (Back)

	glVertex3f(-1.0f, 1.0f,-1.0f);                  // Bottom Left Of The Quad (Back)

	glVertex3f( 1.0f, 1.0f,-1.0f);                  // Bottom Right Of The Quad (Back)

	glColor3f(0.0f,0.0f,1.0f);                      // Set The Color To Blue

	glVertex3f(-1.0f, 1.0f, 1.0f);                  // Top Right Of The Quad (Left)

	glVertex3f(-1.0f, 1.0f,-1.0f);                  // Top Left Of The Quad (Left)

	glVertex3f(-1.0f,-1.0f,-1.0f);                  // Bottom Left Of The Quad (Left)

	glVertex3f(-1.0f,-1.0f, 1.0f);                  // Bottom Right Of The Quad (Left)

	glColor3f(1.0f,0.0f,1.0f);                      // Set The Color To Violet

	glVertex3f( 1.0f, 1.0f,-1.0f);                  // Top Right Of The Quad (Right)

	glVertex3f( 1.0f, 1.0f, 1.0f);                  // Top Left Of The Quad (Right)

	glVertex3f( 1.0f,-1.0f, 1.0f);                  // Bottom Left Of The Quad (Right)

	glVertex3f( 1.0f,-1.0f,-1.0f);                  // Bottom Right Of The Quad (Right)

	glEnd();                                            // Done Drawing The Quad

	return;
}